<title>Support Logical Resources</title>
<table border="0" cellspacing="5" cellpadding="2" width="100%">
  
    <tr> 
      
    <td align="left" valign="top" bgcolor="#0080c0"> <b><font color="#ffffff" face="Arial,Helvetica"> 
      Eclipse 3.1 - Plan item</font></b> </td>
    </tr>
</table>
<h1>Support Logical Resources</h1>
This document outlines the state of the Eclipse Platform <strong>Support Logical 
Resources</strong> plan item. Interested parties should review this document and 
verify that their use cases are reflected in the requirements then later that 
the solution provided satisfies their needs. Feedback is strongly encouraged and 
may be provided on the platform-team-dev mailing list or in the <a
 href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37723">bug report</a> for 
this plan item.
<p class=MsoNormal>This is the plan item:</p>

<blockquote> 
  <p>"<em>The Eclipse Platform supports a strong physical view of projects, 
    files, and folders in the workspace. However, there are many situations where 
    a physical view is not the most salient or useful for many purposes. In some 
    cases, multiple distinct objects happen to be stored in a single file, like 
    an archive. Conversely, in other cases, something that is logically a single 
    object is stored across multiple files. This discrepancy between logical and 
    physical creates problems for common operations such as searching, comparing, 
    and versioning, which need to work in the physical realm. Eclipse should support 
    some way of mapping between a logical view and the physical organization of 
    files on disk.</em>"</p>
  <p>Last Modified: August 12th, 2004</p>
</blockquote>
<h1>Motivation</h1>
<p>By definition Eclipse supports logical resources. It's a "an open extensible 
  IDE for anything and nothing in particular". The applications that are built 
  with it can be tailored to a particular problem domain and the workbench extensions 
  can be used to provide support for the logical model. What Eclipse really doesn't 
  support is integrating tools at the logical model level. It's simple: to integrate 
  two plugins in Eclipse either one plugin must know about the other (through 
  a plugin reference), or both plugins must depend on some common plugin. While 
  the first option is satisfactory for a few cases, the second case is the most 
  common and the most problematic. To illustrate, consider the Eclipse SDK itself. 
  In the SDK, the Resources plugin acts as the common plugin that other plugins 
  use as a point of intergration (e.g. Team, Search, Compare, JDT). Thus, the 
  common model between these plugins is the resource model defined by the Resources 
  plugin.This model is basically the same as the physical file system model and 
  does not provide integration for any other logical models.</p>
<p>As you will see later, even the users of the SDK (JDT+CVS+Resources) can observe 
  some of the problems associated with the lack of support for logical resources 
  and the implicit mapping to physical resources. The lack of a logical integration 
  point causes the co-existance of plugins in Eclipse to be error prone for the 
  user. The next sections will examine the relationships between logical and physical 
  resources and outline the visible problems with Eclipse 2.1. </p>
<h2>Existing Bugs</h2>
<p>Bug <A href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=32582">32582</a> 
  logical to physical mapping problem , 1 model element = 2 Files problem<br>
  Bug <A href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=3979">3979</a> [CVS 
  Decorator] show version info works incorrectly for sub packages (1GFDIEB)</p>
<h2>Logical Resources</h2>
<p>Whereas logical resources are elements of the application that model the data/processes 
  of a particular problem domain, the physical resources are the file system resources 
  (e.g. files and folders) into which an application will eventually transform 
  their application model for storage. Applications that don't use file system 
  resources are not being considered as part of this plan item. For example, an 
  application that stores it's application data directly into a database.</p>
<p>The following table enumerates concrete examples of how logical and physical 
  resources are used in current applications integrated into Eclipse.</p>
<p><a name="#table1"></a>Table 1: Example logical to physical uses</p>
<table width="100%" border="1">
  <tr> 
    <td width="23%"><div align="center"><strong>Relationships</strong></div></td>
    <td width="77%"><div align="center"><strong>Examples</strong></div></td>
  </tr>
  <tr> 
    <td><p>logical (1) &lt;-&gt; (*) physical</p>
      <p>one logical to many physical</p></td>
    <td valign="top"><p><a name="#1a"></a>(<strong>1a</strong>) EJB maps to several physical files: 
        (WSAD + XDE Tester). This is the most common case we have found. </p>
      <blockquote> 
        <p>/src/org/app/bean.java<br>
          /src/org/app/beanr.java<br>
          /src/org/app/beanlocal.java</p>
      </blockquote>
      <p><em>Note: If one of the logical resource's files was deleted who would 
        remember that the file used to exist and is an outgoing deletion or that 
        there is an incoming addition to the logical resource?</em></p>
      <p><a name="#1b"></a>(<strong>1b</strong>) Composite Object (logical) maps to several changed 
        physical resources. (Rational XDE)</p>
      <p><em>Note</em>: <em>With 1 to many relationship there is always the complication 
        that arises if the logical element maps to files in an other project? This 
        would cause many problems in the current Team plugin.</em></p></td>
  </tr>
  <tr> 
    <td><p>logical (*) &lt;-&gt; (1) physical</p>
      <p>many logical to one physical</p></td>
    <td valign="top"><p><a name="#2a"></a>(<strong>2a</strong>) Methods in a class map to their 
        containing class file. (JDT)</p>
      <p><a name="#2b"></a>(<strong>2b</strong>) Archive files (zip, jar) can be seen as a logical 
        and the contents of the archive all map to the same physical.(JTD + all)</p></td>
  </tr>
  <tr> 
    <td><p>logical (1) &lt;-&gt; (1) physical</p>
      <p>one logical to one physical</p></td>
    <td valign="top"><p><a name="#3a"></a>(<strong>3a</strong>) A Java Package maps to a folder 
        but a package does not include sub folders (e.g. they are shallow). (JDT)</p>
      <p><a name="#3b"></a>(<strong>3b</strong>) A UML class maps to a file. For example, in a UML 
        application a class could be stored in a single file called 'x435dsds.umlclass'. 
        The reason it's a logical is that the user of the application will never 
        be concerned about the actual file name or even the folder it's stored 
        in. (XDE)</p></td>
  </tr>
</table>
<h2>Not very adaptable</h2>
<p>Object contributions and decorators are key mechanisms for providing rich
  integration between tools. Using object contributions and adaptable objects,
  any plugin
  
  can provide actions and decorators that will show in another plugin's view.  </p>
<p>Since IResource is the lowest common integration class and
  is strongly mapped to its physical storage as files and folders, the integration
  point for actions and decorators cannot be the logical types in the view. 
  The actions will consequently  use the adaptable type from the selection
  to perform the
  action or the decorator the resource from the getImage request.</p>
<p>Here is an example to illustrate the problem with the CVS plugin. When running 
  a CVS commit action in the packages view the action doesn't know that the IFolder 
  is a Java package and is a shallow namespace. It will use the selection and 
  traverse the selected IContainer using IContainer.members() and commit all child 
  resources. This is the same when the CVS outgoing decorator is shown on a package. 
  It will reflect the deep outgoing state of the IContainer. This can lead to 
  unexpected behavior because the user expected the action to run on the model 
  that the action was displayed on.</p>
<p>Example object contribution for the CVS commit action:</p>
<pre>
&lt;extension point="org.eclipse.ui.popupMenus"&gt;<br> &lt;objectContribution<br>  objectClass="org.eclipse.core.resources.IResource"<br>  adaptable="true"<br>  id="org.eclipse.team.ccvs.ui.IResourceContributions"&gt;<br> &lt;filter<br>  name="projectPersistentProperty"<br>  value="org.eclipse.team.core.repository=org.eclipse.team.cvs.core.cvsnature"&gt;<br> &lt;/filter&gt;<br> &lt;action<br>  label="Commit"<br>  tooltip="Commit resource to CVS repository"<br>  class="org.eclipse.team.internal.ccvs.ui.actions.CommitAction"<br>  menubarPath="team.main/group3"<br>  id="org.eclipse.team.ccvs.ui.commit"&gt;<br> &lt;/action&gt;
 &lt;objectContribution&gt;
&lt;/extension&gt;
</pre>
<p>Example code run in the commit action to calculate the resources to commit:</p>
<pre>public static Object[] getSelectedAdaptables(ISelection selection)    {
  ArrayList result = null;
  if (!selection.isEmpty()) {
    result = new ArrayList();
    Iterator elements = ((IStructuredSelection) selection).iterator();
    while (elements.hasNext()) {
      Object adapter = getAdapter(elements.next(), IResource.class);
      if (c.isInstance(adapter)) {
        result.add(adapter);
      }
    }
   }
   if (result != null &amp;&amp; !result.isEmpty()) {
   return (Object[])result.toArray((Object[])Array.newInstance(IResource.class, result.size()));
  }
  return (Object[])Array.newInstance(IResource.class, 0);
}</pre>
<p>Example code for defining an IResource adaptable decorator:</p>
<pre>&lt;extension
  point="org.eclipse.ui.decorators"&gt;
    &lt;decorator objectClass="org.eclipse.core.resources.IResource"
     adaptable="true"
     label="%DecoratorStandard.name"
     state="false"
     lightweight= "true"
     quadrant = "BOTTOM_RIGHT"
     class="org.eclipse.team.internal.ccvs.ui.CVSLightweightDecorator"
     id="org.eclipse.team.cvs.ui.decorator"&gt;
    &lt;description&gt;
      %DecoratorStandard.desc
    &lt;/description&gt;
  &lt;/decorator&gt;
&lt;/extension&gt;</pre>
<h2>    Decorators</h2>
<p>When the CVS decorator decorates a logical container in a view, the desire 
  is to decorate parents with the dirty indicator if one or more of their logical 
  children are dirty. To do this properly, the decorator would need to query the 
  dirty status of each of the logical children of the container. This can be a 
  costly operation as each child may itself be a logical container. We have optimized 
  the dirty decoration by caching folder dirty states. This optimization becomes 
  far more complicated with logical models where the caching must be based on 
  this alternate model (i.e. the state must be cached for each model).</p>
<p>             
                 
                
                 
         In addition, often decorators rely on&nbsp;IResource change 
  events to re-calculate some new state. In the case of a 
  logical elements representing several physical resources there is no easy way of associated 
  a IResource change event to its files and the actual logical element.</p>
<h2>Views</h2>
<p>It would be nice to see the Java logical view in the Synchronize view or the 
  CVS Repositories View. However, the entries in these views may not be IResources 
  so an IResource independent mapping mechanism would be required. This could 
  be a considerable amount if work for anyone providing a logical model. This 
  problem is partly being addressed by the introduction of customizable content 
  providers as described in the <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-ui-home/navigator-proposal/general_purpose_navigator_proposal.html">Generic 
  Navigator</a> item.</p>
<p>Also if an action prompts the user, for example to add resources to CVS, what 
  icons and labels are used in the dialog? It would be nice to show those that 
  are most familiar to the user. </p>
<h2>Change Sets</h2>
<p>Consider a user's action as a logical change, for example, the user renames 
  a class using the JDT refactoring action. In the user's mind he 'renamed a class' 
  and as a result there has been many other file changes. Currently there is not 
  way of capturing these logical actions and associating the set of affected resources. 
  This problem manifests itself more in tools where almost every change to the 
  model has side effects.</p>
<h2>File based tools</h2>
<p>Some tools that integrate into Eclipse are file based and don't use IResources.
  And thus wouldn't be able to operation logical elements.</p>
<h1>Possible Solution Approaches</h1>
<p>There are basically two approaches to solving the problems discussed above:</p>
<ul>
  <li>A logical model API that can be used by clients (such as repository providers) 
    in order to determine what physical resources constitute model elements.</li>
  <li>A repository provider API that would allow model providers to perform repository 
    operations on their constituant resources.</li>
</ul>
<p>At the present time, the second approach, by itself, is not viable due to its 
  complexity. There is a JSR (JSR 147) that defines such an ineterface but it 
  is not yet finalized and there is not timetable for when it will be. However, 
  to do the first approach properly will require some repository provider API. 
  This is discussed in the following section which propese a solution.</p>
<h1>Proposed Solution</h1>
<p>In this section, we propose a soluton that is centered on API for traversing 
  logical model elements with a minimal amout of repository provider API.</p>
<h2> Logical Model Traversal API</h2>
<p>One possible solution is to introduce a logical model element API that can 
  be the basis for integration between plugins. This solution attempts to solve 
  the most common uses described in <A href="#table1">Table1</a>, namely examples 
  <A href="#1a">1a</a>, <A href="1b">1b</a> and <A href="3a">3a</a>. The <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-ui-home/navigator-proposal/general_purpose_navigator_proposal.html">generic 
  navigator</a> plan item should address the <A href="2b">2b</a> and <A href="3b">3b</a> 
  examples by providing extensions that would allow a logical model to be available 
  to other plugins for display purposes. Finally, <A href="2a">2a</a> is currently 
  solved with the existing <code>IResource</code> adapter mechanism.</p>
<p>Naturally another possible solution would be to change <code>IResource</code> 
  to not be analogous to file system resources. However this scope of change is 
  beyond the 3.0 timeframe and would cause, in my opinion, non-justifiable breaking 
  changes to all plugins.</p>
<h3>IlModelElement</h3>
<p>This solution involves adding an interface to the Resources plugin that maps 
  logical elements to physical ones. The interface is purposely simple with logical 
  model manipulations ommitted. A client can't use this interface to display logical 
  models or gain any interesting additional knowledge about it. In fact, the only 
  way that a plugin will be able to gain access to the model for those purposes, 
  would be via the navigator extensions proposed in the <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-ui-home/navigator-proposal/general_purpose_navigator_proposal.html">generic 
  nagivator</a> plan item.</p>
<p>Current plugins that add object contributions to <code>IResource</code> (CVS, 
  Search, Compare) would have to also add them to <code>IModelElement</code> and 
  honour the biddings provided by the logical resource. Moreover, the plugins 
  that adapted to <code>IResource</code> to these object contributions shown in 
  the context menu should no longer adapt the <code>IResource</code> and instead 
  implement <code>IModelElement</code> (this could be simplified by adding a tag 
  to the objectConribution XML that indicates that it can be used with <code>IResource</code> 
  or <code>IModelElement</code>).</p>
<blockquote> 
  <pre>/**
 * This interface defines an element of an application that models the
 * data/processes of a particular problem domain. This purpose of this interface
 * is to support the transformation of the application model into its underlying
 * file system resources for the purposes of reconciling the model with versions
 * of the model stored in a repository. Hence, this interface provides the
 * bridge between a logical element and the physical resource(s) into which it
 * is stored but does not provide more comprehensive model access or
 * manipulations.
 * 
 * @see IResource
 */
public interface IModelElement {
     
    /**
     * Returns the project which contains this model element. This is a resource
     * handle operation; neither the element nor the resulting project need
     * exist. Model elements may not span multiple projects. In other words, all
     * physical resources that constitute a logical resource are located in the
     * same project.
     * 
     * @return the project handle
     */
    public IProject getProject();
     
    /**
     * Returns one or more traversals that can be used to access all the
     * physical resources that constitute the logical resource. A traversal is
     * simply a set of resources and the depth to which they are to be
     * traversed. This method returns an array of traversals in order to provide
     * flexibility in describing the traversals that constitute a model element.
     * A depth is included to allow the clients of this interface (most likely
     * repository providers) an opportunity to optimize the operation and also
     * ensure that resources that were or have become members of the model
     * element are included in the operation.
     * 
     * Implementors of this interface should ensure, as much as possible, that
     * all resources that are or may be members of the model element are
     * included. For instance, a model element should return the same list of
     * resources regardless of the existance of the files on the file system.
     * For example, if a logical resource called "form" maps to "/p1/form.xml"
     * and "/p1/form.java" then whether form.xml or form.java existed, they
     * should be returned by this method.
     * 
     * In some cases, it may not be possible for a model element to know all the
     * resources that may consitite the element without accessing the state of
     * the model element in another location (e.g. a repository). This method is
     * provided with a context which, when provided, gives access to
     * the members of correcponding remote containers and the contenst of
     * corresponding remote files. This gives the model element the opportunity
     * to deduce what additional resources should be included in the traversal.
     * 
     * @param context gives access to the state of
     *            remote resources that correspond to local resources for the
     *            purpose of determining traversals that adequately cover the
     *            model element resources given the state of the model element
     *            in another location. A null may be provided, in
     *            which case the implementor can assume that only the local
     *            resources are of interest to the client.
     * @param monitor a progress monitor
     * @return a set of traversals that cover the resources that constitute the
     *         model element
     */
    public ITraversal[] getTraversals(IModelContext context,
            IProgressMonitor monitor) throws CoreException;
}</pre>
</blockquote>
<h3>ITraversal</h3>
<p>A logical model element can be made up of one or more traversals that define 
  the physical resources that make up the model element. Traversals are used to 
  allow the clients of the traversal to optimize their operations based on the 
  depth of the resources being traversed.</p>
<blockquote>
  <pre>/** 
 * A model element traversal is simply a set of resources and
 * the depth to which each are to be traversed. A set of traversals
 * is used to describe the resources that constitute a model element.
 *
 * @see org.eclipse.core.resources.IResource
 * @see org.eclipse.core.resources.model.IModelElement
 */
public interface ITraversal {
   
    /**
     * Returns the project which contains the resources that
     * make up this taversal.
     * 
     * @return the project handle
     */
    public IProject getProject();
   
    /**
     * Returns the file system resource(s) for this traversal. 
     * The returned resources must be contained within the same project 
     * and need not exist in the local file system.
     * 
     * The traversal of the returned resources should be done considering
     * the flag returned by getDepth. If a resource returned by a 
     * traversal is a file, it should always be visited. If a resource of a traversal
     * is a folder then files contained in the folder can only be visited if the folder is
     * IResource.DEPTH_ONE or IResource.DEPTH_INFINITE. 
     * Child folders should only be visited if the depth is IResource.DEPTH_INFINITE.
     */
    public IResource[] getResources();
    
    /**
     * Return the depth to which the resources should be traversed.
     * @return the depth to which the physical resources are to be traversed
     * (one of IResource.DEPTH_ZERO, IResource.DEPTH_ONE or IResource.DEPTH_INFINITE)
     */
    public int getDepth();
}</pre>
</blockquote>
<p>For some model elements, simple traversals can be used to describe the element. 
  For instance, here is an example traversal that represents a Java package.</p>
<blockquote>
  <pre>/**
 * An example traversal for a Java package
 */
public class JavaPackageTraversal implements ITraversal {
    IContainer javaPackage;
    public JavaPackageTraversal(IContainer javaPackage) {
        this.javaPackage = javaPackage;
    }
    public IProject getProject() {
        return javaPackage.getProject();
    }
    public IResource[] getResources() {
        return new IResource[] { javaPackage };
    }
    public int getDepth() {
        return IResource.DEPTH_ONE;
    }
}</pre>
</blockquote>
<p>The next example class shows a traversal for a fixed set of files. The chosen 
  example is for the data files that define the properties of a plugin in Eclipse. 
  The same files are always returned even if they don't exist locally. It is up 
  to the client of the interface in this case to decide how to handle the files 
  that don't exist locally. If the client is a repository and the operation is 
  an update to fetch the latest contents from the server, then the repository 
  provider would fetch the files from the server if they now esist there or ignore 
  them if they don't exist either locally or remotely.</p>
<blockquote> 
  <pre>/**<br> * An example of a fixed traversal that always includes<br> * a certain set of files even if they don't exist <br> * locally<br> */<br>public class PluginDataTraversal implements ITraversal {<br>    IProject pluginProject;<br>    public PluginDataTraversal(IProject project) {<br>        this.pluginProject = project;<br>    }<br>    public IProject getProject() {<br>        return pluginProject;<br>    }<br>    public IResource[] getResources() {<br>        return new IResource[] {<br>                pluginProject.getFile(new Path(&quot;plugin.xml&quot;)),<br>                pluginProject.getFile(new Path(&quot;plugin.properties&quot;)),<br>                pluginProject.getFile(new Path(&quot;build.properties&quot;)),<br>                pluginProject.getFile(new Path(&quot;META-INF/MANIFEST.MF&quot;))<br>        };<br>    }<br>    public int getDepth() {<br>        return IResource.DEPTH_ZERO;<br>    }<br>}</pre>
</blockquote>
<p> Assuming that the plugin data consists of the above mentioned files and the 
  contents of the schema directory, the mdel element class for a plugin's data 
  model could be the following:</p>
<blockquote>
  <pre>/**
 * A plugin model element
 */
public class PluginModel implements IModelElement {
    IProject pluginProject;
    public IProject getProject() {
        return pluginProject;
    }
    public ITraversal[] getTraversals(ITraversalContext context,
            IProgressMonitor monitor) throws CoreException {
        return new ITraversal[] {
            new PluginDataTraversal(pluginProject),
            new ITraversal() {
                public IProject getProject() {
                    return pluginProject;
                }
                public IResource[] getResources() {
                    return new IResource[] {
                        pluginProject.getFolder("schema")
                    };
                }
                // Traverse the folder deeply to include all children
                public int getDepth() {
                    return IResource.DEPTH_INFINITE;
                }
            }
        };
    }
}</pre>
</blockquote>
<h3>IModelContext</h3>
<p>One of the advantages of a logical model traversal API is that it allows the 
  repository provider to implement any operations they desire in terms of logical 
  resources (e.g. update, commit, tag, dirty decoration, etc.). However, the context 
  of the operation may imply that resources that don't exist locally should be 
  included in the operation. This is not a problem for some logical models. For 
  instance, a java package is a container visited to a depth of one. Also, the 
  plugin example knows all the files that vould potentially be involved, even 
  if they don't exist locally. Given this, a repository provider can easily determine 
  that outgoing deletions should be included when committing or that incoming 
  additions should be included when updating.</p>
<p>However, properly determining the set of traversals that adequately cover a 
  model element gets more complicated if the resources that constitute the element 
  depend of the contents of a manifest file (or some other similar mechanism) 
  and may change over time. In this case, it is possible that the model element 
  could access the contents of the manifest file as contained in the remote location. 
  Given this ability, the model element provider is provided with enough context 
  about the operation to the logical model element so a set of traversal can be 
  returned that adequately cover all resources that constitute the model element. 
</p>
<p>This has led to the definition of the following <code>IModelContext</code> 
  interface. </p>
  
<blockquote>
  <pre>/**
 * A model context provides a model element with a view of the remote state
 * of a local resource as it relates to a repository operation that is in
 * progress. A repository provider can pass an instance of this interface to a
 * model element when obtaining a set of traversals for a model element. This
 * allows the model element to query the remote state of a resource in order to
 * determine if there are resources that exist remotely but do not exist locally
 * that should be included in the traversal.
 */
public interface IModelContext {
 
    /**
     * Return whether the contents of the corresponding remote differs from the
     * content of the local file. This can be used by clients to determine if
     * they nee to fetch the remote contents in order to determine if the
     * resources that constitute the model element are different in another
     * location.
     * 
     * @param file the local file
     * @param monitor a progress monitor
     * @return whether the contents of the corresponding remote differs from the
     *         content of the local file
     * @throws CoreException if this method fails. Reasons include:
     *           - The corresponding remote resource does not exist (status
     *             code will be IResourceStatus.REMOTE_DOES_NOT_EXIST).
     *           - The corresponding remote resource is not a container
     *             (status code will be IResourceStatus.REMOTE_WRONG_TYPE).
     *           - The server communications failed (status code will be
     *             IResourceStatus.REMOTE_COMMUNICATION_FAILURE).
     */
    public boolean contentDiffers(IFile file, IProgressMonitor monitor)
            throws CoreException;
 
    /**
     * Returns an instance of IStorage in order to allow the
     * caller to access the contents of the remote that corresponds to the given
     * local resource. The provided local file handle need not exist locally. A
     * exception is thrown if the corresponding remote resource does not exist
     * or is not a file.
     * 
     * This method may be long running as a server may need to be contacted to
     * obtain the contents of the file.
     * 
     * @param file the local file
     * @param monitor a progress monitor
     * @return a storage that provides access to the contents of the local
     *         resource's corresponding remote resource
     * @throws CoreException if this method fails. Reasons include:
     *           - The corresponding remote resource does not exist (status
     *             code will beIResourceStatus.REMOTE_DOES_NOT_EXIST).
     *           - The corresponding remote resource is not a file (status
     *             code will be IResourceStatus.REMOTE_WRONG_TYPE).
     *           - The server communications failed (status code will be
     *             IResourceStatus.REMOTE_COMMUNICATION_FAILURE).
     */
    public IStorage fetchContents(IFile file, IProgressMonitor monitor)
            throws CoreException;

    /**
     * Returns the list of member resources whose corresponding remote resources
     * are members of the corresponding remote resource of the given local
     * container. The container need not exist locally and the result may
     * include entries that do not exist locally and may not include all local
     * children. An empty list is returned if the remote resource which
     * corresponds to the container is empty. An exception is thrown if the
     * corresponding remote does not exist or is not capable of having members.
     * 
     * This method may be long running as a server may need to be contacted to
     * obtain the members of the containers corresponding remote resource.
     * 
     * @param container the local container
     * @param monitor a progress monitor
     * @return a list of member resources whose corresponding remote resources
     *         are members of the remote counterpart of the given container
     * @throws CoreException if this method fails. Reasons include:       
     *           - The corresponding remote resource does not exist (status
     *             code will be IResourceStatus.REMOTE_DOES_NOT_EXIST).
     *           - The corresponding remote resource is not a container
     *             (status code will be IResourceStatus.REMOTE_WRONG_TYPE).
     *           - The server communications failed (status code will be
     *             IResourceStatus.REMOTE_COMMUNICATION_FAILURE).
     */
    public IResource[] fetchMembers(IContainer container,
            IProgressMonitor monitor) throws CoreException;
}</pre>
</blockquote>
<p>Although this can be thought of as a repository provider API, it bypasses the 
  complexity by allowing the repository provider to implement the interface in 
  a maner specific to the operation being performed. For instance, for a commit, 
  the repository provider would provide the contents of files that define the 
  base of a manifest file. In other words, the contents of the file would match 
  the contents before the user modified the model element. This would allow for 
  the inclusion of any outgoing deletions. For an update, the repository provider 
  would provide access to the contents of the file in the repository.</p>
<h3>Issues</h3>
<p>This section is devided into two sections. Client isses which indicate what 
  isses the implementators of the above mentioned interfaces face, and Eclipse 
  Platform issues that will need to be addressed when and if the solution is implemented.</p>
<h4>Client Issues</h4>
<p>There are uncertainties for this solution:</p>
<ul>
  <li>Can all repository providers reasonably implement the ITraversalContext 
    for use by the model elements</li>
  <li>Can the model elements implement the code that makes use of this context 
    to determine what additional resources make up the model</li>
</ul>
<p>Either of these efforts may be non-trivial depending on the structure and functionality 
  of the repository provider's or model provider's Eclispse intergration. </p>
<h4>Eclipse Platform Issues</h4>
<p>The following issues would need to be addressed for this solutions</p>
<ol>
  <li>ObjectContributions have to be duplicated in the plugins that would like 
    to provide both contributions for <code>IResource</code> and <code>ILogicalResource</code>. 
  </li>
  <ul>
    <li>This could be simplified by adding support to tag an objectContribution 
      for use with both interfaces</li>
  </ul>
  <li>Logical classes (e.g. java model, UML) have to implement the interface instead 
    of adapting to it. This is a limitation of the current objectContribution 
    story in the workbench. </li>
  <ul>
    <li>Again, this could be circumvented with support in the UI that does the 
      same magic for <code>ILogicalResource</code> that is done for <code>IResource</code></li>
  </ul>
  <li>Plugins that add object contributions will have to modify their actions 
    to handle logical resources. There should be some standard UI components for 
    showing the mappings. For instance you could show the logical model at the 
    top and in a details part the physical files/folders that will be affected 
    by the operation.</li>
</ol>
<h2>Synchronizing, Comparing and Merging Model Elements</h2>
<p>One aspect that is not covered by logic element traversal but is related to 
  repository operations is the ability to synchronize, compare and merge model 
  elements at the model level as opposed to the file system resource level.</p>
<h3>Synchronize View</h3>
<p>The Synchronize view in Eclipse 3.0 supports an infrastructure for choosing 
  the presentation that is used by the view. However, the types of presentations 
  are limited and are resource based. It is possible, however, to allow the presentation 
  to be determined by the provider of a logical model. Here is a summary of what 
  this would involve:</p>
<ul>
  <li>The Synchronize view presentation is determined using a content provider 
    that is defined by the implementor of the synchronize participant. When synchronizing 
    a logical model element, it would be possible to obtain the content provider 
    to be used from the logical model provider. This would require that all the 
    model elements involved in a sychronize belong to the same model provider 
    (this is probably a requirement we would want anyway).</li>
  <li>The elements in the view would be special model element which we will refer 
    to as synchronize model element (or sync element for short). This element 
    would provide access to an instance of <code>IModelElement</code> that could 
    be used by the repository provider to determine the state of the sync element 
    and the resources to be considered when performing an operation. The repository 
    provider would make use of an <code>IModelContext</code> to obtain the remote 
    version of the model element (and a different context to determine the base 
    for a 3-way compare).</li>
</ul>
<p>This is fairly straightforward given the current structure of the synchronze 
  view (and assuming that the logical model traversal API is in place).</p>
<h3>Compare/Merge Editor</h3>
<p>Just as the logical model provider would be responsible for providing the content 
  provider to be used in the Synchronize view, they would also be reponsible for 
  providing a compare editor that is suitable for comparing and merging a model 
  elements. Input to the compare editor would be the model elements involved and 
  the model contexts for the remote and the base (for a 3-way compare). The logical 
  model provider would be responsible fro generating, comparing and merging the 
  model changes into the local copy of the model.</p>
<p>Another input to the compare editor could be a set of actions so that , for 
  instance, during an update that involves conflicting changes, a &quot;done&quot; 
  action could be provided by the repository provider to indicate that a merge 
  is complete and the local resources should no longer be considered conflicts.</p>
<h3>Issues</h3>
<p>Here are some of the issues for the synchronize view and compare editors:</p>
<ul>
  <li>Again, the main issue here is the ability for the repository provider to 
    provide the context for the base and remote model elements and for the model 
    provider to use this information to generate the proper traversals. If eitehr 
    of these is not provided, then the synchronize view and compare would need 
    to fall back to a straight resource-based presentation.</li>
  <li>Most of the work in this proposal falls on the logical model providers.We 
    would want to provide as much support as possible in the Synchronize and Compare 
    frameworks. We will also provide whatever support possible to repository providers 
    although this will probably be most documentation and examples.</li>
  <li>It may be desirable to show mixed presentations in the synchronize view. 
    For instance, the user may wish the see there logical model vie separated 
    by change set. This is a desirable feature but is not a necessity.</li>
</ul>
</BODY>
</html>